<template>
    <div class="baranch">
        <el-row size="mini" style="height: 100%">
            <!-- 范围 -->
            <el-row class="border-box">
                <!-- 范围属性选择框 -->
                <!-- <el-col :span="5" class="search-wrap">
                    <el-select v-model="boundType" placeholder="范围属性" @change="handleBoundTypeChange" disabled size="mini" style="width: 100%">
                        <el-option
                            v-for="item in boundTypes"
                            :key="item"
                            :label="boundTypeStorage[item]"
                            :title="boundTypeStorage[item]"
                            :value="item"
                        ></el-option>
                    </el-select>
                </el-col> -->
                <!-- 指标种类选择框-->
                <!--<el-col :span="7" class="search-wrap" v-if="boundType === '3'">
                    <el-select
                        v-model="category"
                        @change="handleCategoryChange"
                        :disabled="showData"
                        placeholder="请选择"
                        size="mini"
                        style="width: 100%"
                        filterable
                        multiple
                        collapse-tags
                    >
                        <el-option label="-1 全部" value="-1" :disabled="categoryDis"></el-option>
                        <el-option
                            v-for="item in categoryStorage"
                            :disabled="categoryDisAll"
                            :key="item.dictKey"
                            :label="item.dictKey + ' ' + item.dictKeyName"
                            :value="item.dictKey"
                            :title="item.dictKey + ' ' + item.dictKeyName"
                        ></el-option>
                    </el-select>
                </el-col>-->
                <!-- 模板选择框 -->
                <el-col :span="8" class="search-wrap">
                    <el-select
                        v-model="boundForm.templateCode"
                        placeholder="选择范围模板"
                        size="mini"
                        style="width: 100%"
                        :disabled="showData"
                        title="选择范围模板"
                        filterable
                    >
                        <el-option
                            v-for="i in templateStorageQuery"
                            :key="i.templateCode"
                            :label="i.templateCode + ' ' + i.templateName"
                            :value="i.templateCode"
                            :disabled="['2', '3'].includes(i.modifyType)"
                        >
                        </el-option>
                    </el-select>
                </el-col>
                <!-- 添加模板按钮 -->
                <el-col :span="3" class="search-wrap" style="text-align: left">
                    <el-button :disabled="showData" @click="handleAddTemplate" size="mini" type="primary">添加</el-button>
                </el-col>
                <!-- 范围预览按钮 -->
                <el-col :span="3" class="search-wrap">
                    <el-button @click="handleLookBound" size="mini" style="float: right" :disabled="showData" type="primary">范围预览</el-button>
                </el-col>
                <!-- 刷新按钮 -->
                <el-col :span="2" class="search-wrap">
                    <el-button
                        :disabled="showData"
                        @click="handleRefresh"
                        :loading="refreshBtnLoading"
                        size="mini"
                        icon="el-icon-refresh-right"
                        title="刷新"
                    ></el-button>
                </el-col>
            </el-row>
            <el-row class="border-box">
                <!-- SQL拼接连接符 -->
                <el-col :span="4" class="search-wrap">
                    <el-select v-model="boundForm.sqlSpliceType" placeholder="请选择" :disabled="showData" size="mini">
                        <el-option v-for="i in sqlSplicingTypeStorage" :key="i.dictKey" :label="i.dictKey + ' ' + i.dictKeyName" :value="i.dictKey">
                        </el-option>
                    </el-select>
                </el-col>
                <!-- 范围选择框 -->
                <el-col :span="5" class="search-wrap">
                    <!-- <el-select
                        v-model="boundForm.boundCode"
                        placeholder="证券范围"
                        clearable
                        filterable
                        :disabled="showData"
                        @change="handleBoundChange"
                        size="mini"
                    >
                        <el-option
                            v-for="item in boundStorageQuery"
                            :key="item.boundCode"
                            :label="item.boundCode + '' + item.boundName"
                            :value="item.boundCode"
                        >
                        </el-option> 
                    </el-select> -->
                    <Treeselect
                        ref="treeselect"
                        v-model="boundForm.boundCode"
                        :options="boundStorageTree"
                        :default-expand-level="1"
                        :value-consists-of="'LEAF_PRIORITY'"
                        @select="handleBoundChange"
                        @input="handleBoundChange2"
                        :clearable="true"
                        disableBranchNodes
                        placeholder="请选择证券范围"
                        noOptionsText="暂无数据"
                        noResultsText="无匹配数据"
                        noChildrenText="暂无数据"
                    >
                        <label slot="option-label" slot-scope="{ node }">
                            <span>{{ node.label }}</span>
                        </label>
                    </Treeselect>
                </el-col>
                <!-- 比较方向选择框 -->
                <el-col :span="4" class="search-wrap" :class="{ 'hidden-value': !compareTypes.length && currentNode && currentNode.configId }">
                    <el-select v-model="boundForm.compareType" :disabled="showData" clearable placeholder="比较方向" size="mini">
                        <el-option v-for="c in compareTypes" :key="c" :label="compareDirectionStorage[c]" :value="c"> </el-option>
                    </el-select>
                </el-col>
                <el-col :span="spliceMethods.includes('1') || spliceMethods.includes('2') || spliceMethods.includes('3') ? 4 : 7" class="search-wrap">
                    <!-- 下拉列表数据-多选 -->
                    <div v-if="webShowType === '0'">
                        <el-select
                            v-model="boundForm.boundValues"
                            @change="handleBoundValueChange"
                            filterable
                            multiple
                            collapse-tags
                            :disabled="showData"
                            clearable
                            size="mini"
                            placeholder="请选择"
                        >
                            <el-option
                                v-for="i in boundValueCheckStorage"
                                :key="i.dictKey"
                                :label="i.dictKey + '  ' + i.dictKeyName"
                                :value="i.dictKey"
                            >
                            </el-option>
                        </el-select>
                        <!-- <vxe-pulldown ref="showTypeDown">
                            <template #default>
                                <yh-input
                                    v-model="boundValueShow"
                                    placeholder="请选择"
                                    @focus="showTypeFocusEvent"
                                    class="service-type-input"
                                    size="mini"
                                ></yh-input>
                            </template>
                            <template #dropdown>
                                <div class="my-dropdown">
                                    <div class="accountControlValue-search">
                                        <i class="el-icon-search" style="cursor: pointer"></i>
                                        <yh-input
                                            v-model="boundValueSearchInput"
                                            @keyup.native="boundValueSearch"
                                            placeholder="请选择"
                                            size="mini"
                                        ></yh-input>
                                    </div>
                                    <div>
                                        <el-checkbox-group v-model="boundForm.boundValues" @change="handleBoundValueChange">
                                            <el-checkbox v-for="item in boundValueCheck" :key="item.dictKey" :label="item.dictKey">
                                                {{ item.dictKey + '  ' + item.dictKeyName }}</el-checkbox
                                            >
                                        </el-checkbox-group>
                                    </div>
                                </div>
                            </template>
                        </vxe-pulldown> -->
                    </div>
                    <!-- 数字输入框-整数 -->
                    <yh-input-number
                        v-model="boundForm.boundValuesNum"
                        controls-position="right"
                        :step="1"
                        step-strictly
                        :disabled="showData"
                        @change="handleBoundValueChange"
                        v-if="webShowType === '1'"
                        size="mini"
                    ></yh-input-number>
                    <!-- 大数据选择 -->
                    <div v-if="webShowType === '2' && !separateValid" style="display: flex">
                        <el-input
                            disabled
                            style="width: calc(100% - 36px)"
                            size="mini"
                            placeholder=""
                            v-model="transValuesShow"
                            :title="transValuesShow"
                        ></el-input>
                        <el-button @click="selectKeyValueClick" type="primary" icon="el-icon-search" size="mini" style="margin-left: 2px">
                        </el-button>
                    </div>
                    <!-- 时间选择框 -->
                    <el-date-picker
                        v-model="boundForm.boundValuesDate"
                        type="date"
                        placeholder="选择日期时间"
                        size="mini"
                        :disabled="showData"
                        value-format="yyyyMMdd"
                        format="yyyyMMdd"
                        @change="handleBoundValueChange"
                        v-show="webShowType === '3'"
                        style="width: 100%"
                    >
                    </el-date-picker>
                    <!-- 下拉列表数据-单选 -->
                    <el-select
                        v-model="boundValueSelect"
                        v-show="webShowType === '4'"
                        :disabled="showData"
                        @change="handleBoundValueChange"
                        size="mini"
                        filterable
                        placeholder="请选择"
                    >
                        <el-option
                            v-for="item in boundValueCheckStorage"
                            :key="item.dictKey"
                            :label="item.dictKey + ' ' + item.dictKeyName"
                            :value="item.dictKey"
                        >
                        </el-option>
                    </el-select>
                    <!-- 数字输入框-小数 -->
                    <el-input-number
                        v-model="boundForm.boundValuesNum"
                        controls-position="right"
                        :disabled="showData"
                        :precision="6"
                        :max="10000000000000"
                        @change="handleBoundValueChange"
                        v-if="webShowType === '5'"
                        size="mini"
                    ></el-input-number>
                    <!-- 树下拉框 招商基金特有的 -->
                    <!-- <Treeselect
                        v-if="webShowType === '7'"
                        v-model="boundForm.boundValues"
                        multiple
                        :options="boundValueCheckStorage"
                        @input="handleBoundValueChange"
                        :default-expand-level="1"
                        :value-consists-of="'LEAF_PRIORITY'"
                        :clearable="true"
                        :limit="1"
                        :limitText="limitText"
                        noOptionsText="暂无数据"
                        noResultsText="无匹配数据"
                        noChildrenText="暂无数据"
                        class="type7select"
                        placeholder="请选择"
                    >
                    </Treeselect> -->
                </el-col>
                <el-col :span="4" class="search-wrap">
                    <el-checkbox
                        size="mini"
                        v-model="separateValid"
                        @change="handleSeparateValid"
                        :disabled="!showSeparateValid"
                        style="margin-top: 4px"
                        >单独控制</el-checkbox
                    >
                </el-col>

                <el-col
                    v-show="spliceMethods.includes('1') || spliceMethods.includes('2') || spliceMethods.includes('3')"
                    :span="3"
                    class="search-wrap"
                >
                    <el-select v-model="boundForm.spliceMethod" placeholder="请选择控制维度" size="mini">
                        <el-option
                            v-for="(value, key) in controlTypeOptions"
                            :key="key"
                            :value="key"
                            :label="value"
                            v-show="spliceMethods.includes(key)"
                        >
                        </el-option>
                    </el-select>
                </el-col>
            </el-row>
            <el-row class="border-box" style="height: calc(100% - 80px)">
                <el-col :span="22" class="search-wrap" style="height: 100%">
                    <div class="tree-box">
                        <el-tree
                            ref="tree"
                            id="tree"
                            default-expand-all
                            :data="entryBranchConfigsTreeQuery"
                            :props="treeProps"
                            @node-click="handleTreeClick"
                            :expand-on-click-node="false"
                            node-key="configId"
                            :check-on-click-node="true"
                        >
                            <span class="custom-tree-node" slot-scope="{ node, data }">
                                <span :class="boundTitleStyle(data)">
                                    {{ node.label }}
                                </span>
                                <i
                                    class="el-icon-setting"
                                    style="font-size: 20px; margin-left: 3px; vertical-align: bottom"
                                    :style="showResolveKey(data)"
                                    @click="handeBoundExtend(data)"
                                />
                                <ItemBoundExtendModel
                                    :showModal="showBoundExtendModel"
                                    :selectWebSqlValues="selectWebSqlValues5"
                                    :boundConfigExtends="boundConfigExtends"
                                    :record="FiveData"
                                    @handleBoundExtendModel="handleBoundExtendModel"
                                    v-if="showBoundExtendModel"
                                ></ItemBoundExtendModel>
                            </span>
                        </el-tree>
                    </div>
                </el-col>

                <el-col :span="2" class="search-wrap">
                    <el-button
                        size="mini"
                        icon="el-icon-circle-plus-outline"
                        @click="handleAddTree"
                        title="添加"
                        :disabled="showData"
                        type="primary"
                    ></el-button>
                    <div style="margin-top: 10px">
                        <el-button
                            size="mini"
                            icon="el-icon-check"
                            title="编辑"
                            :disabled="showData"
                            @click="handleUpdateTree"
                            type="primary"
                        ></el-button>
                    </div>

                    <div style="margin-top: 10px">
                        <el-button
                            size="mini"
                            icon="el-icon-minus"
                            type="danger"
                            :disabled="showData"
                            title="删除配置"
                            @click="handleDeleteTree"
                        ></el-button>
                    </div>
                    <!-- <div style="margin-top: 10px">
                            <el-button size="mini" title="校验配置" icon="el-icon-warning-outline" type="primary" @click="showTreeAndDiv"></el-button>
                        </div> -->
                </el-col>
            </el-row>
        </el-row>

        <!-- 大数据穿梭框 -->
        <el-dialog drag :visible.sync="editLargeDataDialog.visible" width="800px" v-loading="loading">
            <div style="height: fit-content">
                <RiskSettingInline
                    :boundCode="boundForm.boundCode"
                    ref="trans"
                    url="/original/showBigData"
                    index-key="dictKey"
                    left-placeholder="编号/名称"
                    right-placeholder="编号/名称"
                    :columns="tranColumns"
                    :right-table-data="rightTranData"
                    :search-names="['dictKey', 'dictKeyName']"
                />
            </div>
            <div slot="footer" class="dialog-footer">
                <el-button size="mini" @click="editLargeDataDialog.visible = false"> 取 消 </el-button>
                <el-button size="mini" type="primary" @click="handleEditTrans">确 定 </el-button>
            </div>
        </el-dialog>

        <!-- 范围预览 -->
        <el-dialog drag title="资产范围定位查找" :visible.sync="lookBoundVisible" width="600px" destroy-on-close>
            <div style="height: 336px">
                <el-input placeholder="请输入资产明细" v-model="lookBoundSearchVal" size="mini" style="width: 100%">
                    <i slot="suffix" class="el-input__icon el-icon-search" @click="getLookBoundList"></i>
                </el-input>
                <el-table
                    :data="lookBoundTableData"
                    border
                    size="mini"
                    style="width: 100%; margin-top: 10px"
                    max-height="270px"
                    v-loading="lookBoundLoading"
                >
                    <el-table-column label="范围类型" show-overflow-tooltip>
                        <template slot-scope="scope">
                            <span>
                                {{ scope.row.boundType }}
                                {{ boundTypeStorage[scope.row.boundType] }}
                            </span>
                        </template>
                    </el-table-column>
                    <el-table-column label="资产名称" show-overflow-tooltip>
                        <template slot-scope="scope">
                            <span>
                                {{ scope.row.boundCode }}
                            </span>
                            <span>
                                {{ scope.row.boundName }}
                            </span>
                        </template>
                    </el-table-column>
                    <el-table-column prop="boundType" label="资产明细" show-overflow-tooltip>
                        <template slot-scope="scope">
                            <span>
                                {{ scope.row.key || '' }}
                            </span>
                            <span>
                                {{ scope.row.name || '' }}
                            </span>
                        </template>
                    </el-table-column>
                </el-table>
                <div class="block">
                    <el-pagination
                        background
                        @current-change="getLookBoundList"
                        layout="total, prev, pager, next"
                        :total="lookBoundPage.total"
                        :page-size="lookBoundPage.pageSize"
                        :current-page.sync="lookBoundPage.currentPage"
                    >
                    </el-pagination>
                </div>
            </div>
            <div slot="footer" class="dialog-footer">
                <el-button size="mini" @click="handleLookBoundClose"> 取 消 </el-button>
            </div>
        </el-dialog>
    </div>
</template>
<script lang="ts">
import { Component, Prop, Watch } from 'vue-property-decorator';
import DictionConstUtil from '@/utils/diction-const-util';
import { mixins } from 'vue-class-component';
import RiskEmitter from '@/common/mixis/risk-emitter.vue';
import XEUtils from 'xe-utils';
import { DialogVO } from '@yhfin/biz';
import RiskSettingInline from '@/common/components/risk-setting-inline.vue';
import ItemBoundExtendModel from '@/pages/baseparam/fund-group-setting/item-bound-extend-model.vue';
import ItemCalcExtendModel from '@/pages/baseparam/fund-group-setting/item-calc-extend-model.vue';
import { arrayToTree, treeToArray, recursivefilter } from '@/utils/tools';

export interface pages {
    total?: number;
    pageSize?: number;
    currentPage?: number;
    totalPage?: number;
}

export interface dynamicDataReqVO {
    dynamicCode?: string;
    boundCode?: string;
    boundValues?: any[];
    compareType?: string; // 比较方向
    boundValueNames?: any[]; //
    boundGroupValid?: boolean; // 是否是组配置
    parentId?: number;
    configId?: number;
    children?: any[];
    webSqlType?: '';
    webBoundName?: '';
    webCompareType?: '';
    webBoundvalue?: '';
    webgroupType?: '';
    boundExtend?: ''; // 范围模板5额外配置字段
    separateValid?: boolean; // 单独控制(是否同申报)
    sqlSpliceType?: string; // sql拼接符
    groupType?: string; // 范围配置组控制类型
    showBoundExtend?: boolean;
    templateCode?: any;
    boundValuesNum?: string | number; // 数字框
    boundValuesDate?: any; // 日期框
    spliceMethod?: string;
}

@Component({
    name: 'RiskBoundSetting',
    components: { ItemBoundExtendModel, RiskSettingInline, ItemCalcExtendModel },
})
export default class RiskBoundSetting extends mixins(RiskEmitter) {
    // @Prop({ required: true }) riskEntryBranchList!: any[]; // 分支列表数据
    @Prop() showData: boolean;
    @Prop() entryBranch: any; // 选中因子数据
    @Prop({ default: 'look' }) status!: string; // 页面状态
    @Prop({ default: '0' }) type!: string | number; // 页面状态
    @Prop({ default: [] }) boundTypes?: any[]; // 因子关联原始范围属性
    @Prop() focusOutsideIndex;
    @Prop() alwaysOpenBranch;
    @Prop() factorStorage;

    boundTypeStorage: any = {}; // 范围属性仓库
    boundType: any = null; // 当前选中范围属性

    categoryStorage: any[] = []; // 指标种类仓库
    category: string[] = ['-1']; // 当前选中种类
    categoryDis: boolean = false;
    categoryDisAll: boolean = true;

    templateStorage: any[] = []; // 模板仓库

    boundStorage: any[] = []; // 范围指标仓库
    // factorStorage: any[] = [];
    boundEnum: any = {}; // 范围指标对象

    SHOW_SECURITY = process.env.ENV_CONFIG === 'project' ? window.project_config.showSecurity : process.env.SHOW_SECURITY;
    currentLevelSymbol: string = '0'; // 当前层级标识

    sqlSplicingTypeStorage: any[] = []; // SQL拼接符仓库

    compareDirectionStorage: any = {}; // 比较方向仓库
    compareTypes: any[] = []; // 当前可选比较方向

    boundForm: dynamicDataReqVO = {
        templateCode: undefined,
        sqlSpliceType: '0',
        compareType: '',
        boundValues: [],
        boundValueNames: [],
        boundValuesNum: '',
        boundValuesDate: '',
        spliceMethod: '0',
        separateValid: false, // 单独控制
    };

    entryBranchConfigs: any[] = []; // 范围分支一维数组数据
    entryBranchConfigsTree: any[] = []; // 树结构数据

    treeProps = { children: 'children', label: 'label' }; // 树字段绑定

    currentNode: any = {}; // 当前选中节点数据

    configId: number = 2; // 自身id (0,1,2留给最外层)

    refreshBtnLoading: boolean = false; // 刷新按钮loading状态

    webShowType: string = ''; // 前端下拉框展示类型
    boundValueSearchInput: string = ''; // 多选下拉框搜索参数
    boundValueCheckStorage: any[] = []; // 多选下拉框勾选仓库
    transValuesShow: string = ''; // 大数据框所选值回显用
    boundValueSelect: string = ''; // 单选框绑定值

    editLargeDataDialog: DialogVO = new DialogVO(); // 大数据穿梭框
    rightTranData: any[] = []; // 大数据右边已选中数据
    tranColumns: any[] = [
        { label: '编号', prop: 'dictKey', width: 80 },
        { label: '名称', prop: 'dictKeyName', width: 165 },
    ];

    separateValid: boolean = false; // 是否单独控制
    showSeparateValid: boolean = false; // 展示（禁用）单独控制

    lookBoundVisible: boolean = false; // 范围预览dialog
    lookBoundSearchVal: string = ''; // 范围预览搜索框
    lookBoundTableData: any[] = [];
    lookBoundLoading: boolean = false;
    lookBoundPage: pages = { currentPage: 1, pageSize: 20, total: 0, totalPage: 0 };

    spliceMethods: any[] = []; // 当前范围指标的范围类型
    controlTypeOptions: any = { '0': '按证券代码控制', '1': '按产品代码控制', '2': '按冻结代码控制', '3': '按配售代码控制' };

    FiveData: any = {};
    showBoundExtendModel: boolean = false; // 是否打开第五类弹框
    currentBoundExtend: any = {}; // 第五类当前节点数据
    selectWebSqlValues5: any[] = []; // 下拉列表可选值
    boundConfigExtends: any[] = []; // 下拉列表可选值
    timeDelayUnit: any = null;

    calcCurrentNode: any; // 当前选中因子节点数据

    boundListClass: any[] = [];
    treeselectInstance = null;

    boundValueOriginalStorage: any[] = [];

    alwaysOpenBound: boolean = false;

    branchPitch: string = '';
    recordLastBoundCode = ''; // 记录factorCode
    boundVisible: boolean = false; //
    selectBoolean = false;
    iconBoolean = false;
    timer = null;

    async mounted() {
        // if (this.boundTypes && this.boundTypes.length == 0) {
        //     this.boundType = this.boundTypes || '3';
        // } else {

        // }
        // 获取范围属性枚举仓库
        this.boundTypeStorage = DictionConstUtil.BoundType;
        this.getBoundTree();
        // 获取指标种类仓库
        // this.categoryStorage = DictionConstUtil.PojoToList(DictionConstUtil.Category);
        this.categoryStorage = await DictionConstUtil.FNCateGory();
        // 获取所有范围指标仓库
        this.boundStorage = await DictionConstUtil.FNBoundCfg();
        // this.factorStorage = await DictionConstUtil.FNCalculateFactor();
        // 设置范围指标枚举 以便查找
        let boundEnum = {};
        this.boundStorage.forEach(element => {
            boundEnum[element.boundCode] = element;
        });
        if (!boundEnum['-1']) {
            boundEnum['-1'] = '';
        }
        this.boundEnum = boundEnum;
        // 获取比较方向仓库
        this.compareDirectionStorage = DictionConstUtil.CompareDirection;
        // 获取所有模板仓库
        this.templateStorage = await DictionConstUtil.FNBranchBoundTemplate();
        // 获取SQL拼接符仓库
        this.sqlSplicingTypeStorage = DictionConstUtil.PojoToList(DictionConstUtil.SqlSplicingType);

        // this.treeselectInstance = this.$refs.treeselect;
    }

    beforeDestroy() {
        // this.treeselectInstance.$destroy();
        // this.$refs.treeselect.$el.parentNode.removeChild(this.$refs.treeselect.$el);
        if (this.timeDelayUnit) {
            clearTimeout(this.timeDelayUnit);
            this.timeDelayUnit = null;
        }
        // 清除定时器
        clearInterval(this.timer);
        this.timer = null;
    }

    // @Watch('entryControls', { immediate: true, deep: true })
    // watchentryControls() {}
    @Watch('boundForm.boundCode', { immediate: true, deep: true })
    watchFactorCode(newValue, oldValue) {
        // this.recordLastBoundCode = oldValue || '';
        if (this.iconBoolean == false && this.selectBoolean) {
            this.recordLastBoundCode = oldValue || '';
            this.iconBoolean = false;
            this.selectBoolean = false;
        } else if (oldValue == undefined) {
            this.recordLastBoundCode = newValue || '';
            this.iconBoolean = false;
            this.selectBoolean = false;
        }
    }
    /**
     * 监听父组件源数据
     */
    @Watch('entryBranch', { immediate: true, deep: true })
    watchEntryBranch(newData, oldData) {
        this.calcCurrentNode = newData;
        // if (newData) {
        let entryBranchConfigs = newData.entryBranchConfigs || [];
        let cloneData = XEUtils.clone(entryBranchConfigs, true);
        let treeData = XEUtils.toArrayTree(cloneData, { key: 'configId', parentKey: 'parentId' });
        entryBranchConfigs = this.packageBoundType(treeData);
        if (entryBranchConfigs.length) {
            for (let i = 0; i < entryBranchConfigs.length; i++) {
                const element = entryBranchConfigs[i];
                // element.entryBranch = { branchNo: newData.branchNo, factorCode: newData.factorCode };
                element.label =
                    DictionConstUtil.SqlSplicingType[element.sqlSpliceType] +
                    ' ' +
                    (this.boundEnum[element.boundCode]?.boundName || '') +
                    ' ' +
                    (element.boundGroupValid ? '' : this.compareDirectionStorage[element.compareType]) +
                    ' ' +
                    (element.boundValueNames || '') +
                    (element.separateValid ? '单独控制' : '');
            }
        }

        // 未选中数据
        if (JSON.stringify(newData) == '{}') {
            this.boundType = '';
            this.boundForm = {
                templateCode: undefined,
                sqlSpliceType: '0',
                compareType: '',
                boundValues: [],
                boundValueNames: [],
                boundValuesNum: '',
                boundValuesDate: '',
                separateValid: false,
                spliceMethod: '0',
            };
            this.separateValid = false;
        }

        // 当切换因子时 清空所选的范围属性 默认属性交给@Watch('entryBranchConfigs')判断
        if (newData.factorCode && oldData.factorCode && newData.factorCode !== oldData.factorCode) {
            this.boundType = '';
        }

        this.entryBranchConfigs = entryBranchConfigs;
        // }
    }

    /**
     * 监听分支变化渲染树
     */
    @Watch('entryBranchConfigs', { immediate: true, deep: true })
    watchRiskEntryBranch(newData) {
        if (newData) {
            let data = newData.filter(item => item.groupType === '0');
            let cloneData = XEUtils.clone(data, true);

            this.entryBranchConfigsTree = XEUtils.toArrayTree(cloneData, { key: 'configId', parentKey: 'parentId' });

            // 如果该因子下有可配范围属性 && 未选择范围属性
            if (!this.boundType && this.boundTypes.length) {
                // 优先展示有值的范围属性
                for (let i = 0; i < newData.length; i++) {
                    const element = newData[i];
                    if (element.groupType && element.groupType !== '0') {
                        this.boundType = element.groupType;
                        break;
                    }
                }
                // // 如果都没找到 就用第一个范围属性
                if (!this.boundType) {
                    if (this.boundTypes.includes('3')) {
                        this.boundType = '3';
                    } else {
                        this.boundType = this.boundTypes[0];
                    }
                }
            } else if (this.boundType && this.boundTypes.length) {
                // 如果该因子下有可配范围属性 && 选择了范围属性
                // 如果选择的范围属性 不在可选范围之内
                if (!this.boundTypes.includes(this.boundType)) {
                    this.boundType = this.boundTypes[0];
                }
            }
            // 获取最大configId
            let configIds = newData.map(item => item.configId);
            if (configIds.length) {
                this.configId = Math.max(...configIds) + 1;
            }
        }
    }

    /**
     * 过滤树 （范围属性）
     */
    get entryBranchConfigsTreeQuery() {
        // 过滤 最外层并且 + 其他范围属性
        // return this.entryBranchConfigsTree.filter((item: any) => item.boundType === this.boundType && item.groupType === '0');
        // 过滤 最外层并且
        const treeData = this.entryBranchConfigsTree.filter((item: any) => item.groupType === '0');
        let tree = [];
        for (let i = 0; i < this.boundTypes.length; i++) {
            const treeItem = {
                configId: treeData.find(item => item.boundType === this.boundTypes[i])?.parentId || this.boundTypes[i] + '999',
                label: this.boundTypeStorage[this.boundTypes[i]],
                boundType: this.boundTypes[i],
                boundTitle: true,
                children: treeData.filter(item => item.boundType === this.boundTypes[i]),
            };
            tree.push(treeItem);
        }
        let arrTest = [];
        // 调整optionalInvestGroupType顺序
        arrTest = ['3', '8', '1', '0', '2', '10', '6', '5', '4', '7'];
        tree.sort((a, b) => {
            return arrTest.indexOf(a.boundType) - arrTest.indexOf(b.boundType);
        });
        return tree;
    }

    // /**
    //  * 监听父组件 因子分类
    //  */
    // @Watch('type', { deep: true })
    // watchEntryType(newData) {}

    /**
     * 过滤模板 （风险类型 + 复核状态）
     */
    get templateStorageQuery() {
        return this.templateStorage.filter(
            (item: any) => item.boundType === this.boundType && !(item.modifyStatus === '1' && item.modifyType === '1')
        );
    }

    /**
     * 过滤范围指标 (原始关联范围 + 禁用 + 风险类型)
     */
    get boundStorageQuery() {
        let storage: any[];
        if (this.entryBranch.factorCode) {
            // 因子的关联原始范围
            let bounds =
                this.factorStorage.find(item => item.entryCalculateFactorCode === this.entryBranch.factorCode)?.boundCodes?.map(i => i.boundCode) ||
                [];
            storage = this.match(this.boundStorage, bounds);
        } else {
            storage = this.boundStorage;
        }
        let res = storage
            .filter((item: any) => item.validSymbol === '1')
            .sort((a: any, b: any) => a.boundCode.replace(/[^0-9]/gi, '') - b.boundCode.replace(/[^0-9]/gi, ''));
        return res.filter(
            item => item.boundType === this.boundType && ((this.SHOW_SECURITY && item.levelSymbol == this.currentLevelSymbol) || !this.SHOW_SECURITY)
        );
    }

    /**
     * 范围指标树组装
     */
    get boundStorageTree() {
        this.boundStorageQuery.forEach(i => {
            i.id = i.boundCode;
            i.label = i.boundCode + ' ' + i.boundName;
            i.parentId = i.classId;
            // i.isDisabled = true;
        });
        // 根据展示的计算因子向上寻找父级
        let factorKeys = this.boundStorageQuery.map(item => item.parentId);
        factorKeys = [...new Set(factorKeys)]; // 展示因子的所有上层id
        let showTree = []; // 所有需要展示的树节点 （节点下没有因子的不展示）
        factorKeys.forEach(i => {
            const arr = this.findNode(this.boundListClass, i) || [];
            showTree = [...showTree, ...arr];
        });
        showTree = this.uniqueById(JSON.parse(JSON.stringify(showTree)));
        return arrayToTree([...this.boundStorageQuery, ...showTree]);
    }

    /**
     * 获取范围层级关系
     */
    getBoundTree(): void {
        this.$axios({ method: 'get', url: '/original/bound/listClass' }).then((res: any) => {
            if (res) {
                this.boundListClass = res;
            }
        });
    }

    /**
     * 模板添加事件
     */
    handleAddTemplate(): void {
        if (!this.boundForm.templateCode) {
            return;
        }

        this.$axios({ method: 'get', url: '/entry/template/bound/query/' + this.boundForm.templateCode }).then((res: any) => {
            let templateBranch = res.riskEntryBranchs;
            if (!templateBranch || templateBranch.length === 0) {
                return;
            }
            // 获取下一分序号
            let configId = this.configId - 1;
            // 模板数据
            let value = templateBranch[0].entryBranchConfigs;
            if (value.length === 0) {
                return;
            }
            let valueCf = value[0];
            let cpConfigId = valueCf.configId;
            // 判断该范围属性下是否为空，如果为空 创建最外层
            let obj = null;
            let objPid = 0;
            if (!this.entryBranchConfigs.find(item => item.groupType === this.boundType)) {
                obj = {
                    boundGroupValid: true,
                    branchNo: this.entryBranch.branchNo,
                    compareType: '4',
                    configId: this.configId,
                    groupType: this.boundType,
                    parentId: 0,
                    separateValid: false,
                    sqlSpliceType: '0',
                };
                objPid = this.configId;
            } else {
                objPid = this.entryBranchConfigs.find(item => item.groupType === this.boundType).configId;
            }
            // 判断节点插入位置
            let parentId = objPid;
            // let data = templateBranch[0].entryBranchConfigs;
            if (this.currentNode.configId && this.currentNode.boundGroupValid) {
                // 有选中节点 且 选中节点为父节点
                parentId = this.currentNode.configId;

                for (let i = 0; i < templateBranch[0].entryBranchConfigs.length; i++) {
                    const element = templateBranch[0].entryBranchConfigs[i];
                    // 剔除最外层范围
                    if (element.parentId === 0) {
                        element.splice = true;
                    }
                    element.label =
                        DictionConstUtil.SqlSplicingType[element.sqlSpliceType] +
                        ' ' +
                        (this.boundEnum[element.boundCode]?.boundName || '') +
                        ' ' +
                        (this.compareDirectionStorage[element.compareType] || '') +
                        ' ' +
                        (element.boundValueNames || '') +
                        (element.separateValid ? '单独控制' : '');
                    element.configId += configId;
                    element.boundType = this.boundType;
                    if (element.parentId === cpConfigId) {
                        element.parentId = this.currentNode.configId;
                    } else {
                        element.parentId += configId;
                    }
                    this.configId = element.configId;
                }
            } else {
                for (let i = 0; i < templateBranch[0].entryBranchConfigs.length; i++) {
                    const element = templateBranch[0].entryBranchConfigs[i];
                    // 剔除最外层范围
                    if (element.parentId === 0) {
                        element.splice = true;
                    }
                    element.label =
                        DictionConstUtil.SqlSplicingType[element.sqlSpliceType] +
                        ' ' +
                        (this.boundEnum[element.boundCode]?.boundName || '') +
                        ' ' +
                        (this.compareDirectionStorage[element.compareType] || '') +
                        ' ' +
                        (element.boundValueNames || '') +
                        (element.separateValid ? '单独控制' : '');
                    element.configId += configId;
                    element.boundType = this.boundType;
                    if (element.parentId === cpConfigId) {
                        element.parentId = parentId;
                    } else {
                        element.parentId += configId;
                    }
                    this.configId = element.configId;
                }
            }
            this.configId += 1;

            templateBranch = templateBranch.map(item => item.entryBranchConfigs);
            templateBranch = templateBranch[0].filter(item => !item.splice);

            let entryBranchConfigs = [...this.entryBranchConfigs, ...templateBranch];
            if (obj) {
                entryBranchConfigs.push(obj);
            }
            this.packageEntryBranchConfigs(entryBranchConfigs);
            // 取消选中高亮
            this.currentNode = {};
            // 清空选择框
            this.webShowType = '';
            this.separateValid = false;
            this.boundForm = {
                templateCode: undefined,
                sqlSpliceType: '0',
                compareType: '',
                boundValues: [],
                boundValueNames: [],
                boundValuesNum: '',
                boundValuesDate: '',
                separateValid: false,
                spliceMethod: '0',
            };
        });
    }

    /**
     * 刷新事件
     */
    async handleRefresh() {
        this.refreshBtnLoading = true;
        this.getBoundTree();
        // 获取所有范围指标仓库
        this.boundStorage = await (DictionConstUtil.SGUBoundCfg() as any);
        this.yh_message_success('范围指标数据刷新成功');
        // 设置范围指标枚举 以便查找
        let boundEnum = {};
        this.boundStorage.forEach(element => {
            boundEnum[element.boundCode] = element;
        });
        if (!boundEnum['-1']) {
            boundEnum['-1'] = '';
        }
        this.boundEnum = boundEnum;

        // 获取所有模板
        this.templateStorage = (await DictionConstUtil.FNBranchBoundTemplate()) as any;
        this.yh_message_success('范围指标数据刷新成功'); // 这个有问题
        this.refreshBtnLoading = false;
    }

    /**
     * 添加分支事件
     */
    handleAddTree(): void {
        // 范围属性
        this.boundForm.webgroupType = this.boundType;
        // 校验
        if (!this.verifyBoundFormParams()) {
            return;
        }
        // 判断该范围属性下是否为空，如果为空 创建最外层
        let obj = null;
        let objPid = 0;
        if (!this.entryBranchConfigs.find(item => item.groupType === this.boundType)) {
            obj = {
                boundGroupValid: true,
                branchNo: this.entryBranch.branchNo,
                compareType: '4',
                configId: this.configId,
                groupType: this.boundType,
                parentId: 0,
                separateValid: false,
                sqlSpliceType: '0',
            };
            objPid = this.configId;
        } else {
            objPid = this.entryBranchConfigs.find(item => item.groupType === this.boundType).configId;
        }

        // 判断节点插入位置
        let parentId = objPid;
        if (this.currentNode.configId && this.currentNode.boundGroupValid) {
            // 有选中节点 且 选中节点为父节点
            parentId = this.currentNode.configId;
        }
        let label =
            DictionConstUtil.SqlSplicingType[this.boundForm.sqlSpliceType] +
            ' ' +
            (this.boundEnum[this.boundForm.boundCode]?.boundName || '') +
            ' ' +
            (this.compareDirectionStorage[this.boundForm.compareType] || '') +
            ' ' +
            (this.boundForm.boundValueNames || '') +
            (this.boundForm.separateValid ? '单独控制' : '');

        let newData = {
            branchNo: this.calcCurrentNode?.branchNo || 0,
            boundCode: this.boundForm.boundCode,
            // eslint-disable-next-line no-unneeded-ternary
            boundGroupValid: this.boundForm.boundCode ? false : true,
            boundValueNames: this.boundForm.boundValueNames || [],
            boundValues: this.boundForm.boundValues || [],
            compareType: this.boundForm.compareType || '4',
            configId: this.configId + 1,
            groupType: '0',
            parentId,
            separateValid: this.boundForm.separateValid,
            resolveKey: this.boundEnum[this.boundForm.boundCode]?.resolveKey || '',
            sqlSpliceType: this.boundForm.sqlSpliceType,
            boundType: this.boundType,
            boundValuesNum: this.boundForm.boundValuesNum,
            boundValuesDate: this.boundForm.boundValuesDate,
            spliceMethod: this.boundForm.spliceMethod,
            label,
        };

        this.configId += 2;
        let entryBranchConfigs = XEUtils.clone(this.entryBranchConfigs, true);
        if (obj) {
            entryBranchConfigs.push(obj);
        }
        entryBranchConfigs.push(newData);
        this.packageEntryBranchConfigs(entryBranchConfigs);

        // 取消选中高亮
        this.currentNode = {};
        // 清空选择框
        this.webShowType = '';
        this.separateValid = false;
        this.boundForm = {
            templateCode: undefined,
            sqlSpliceType: '0',
            compareType: '',
            boundValues: [],
            boundValueNames: [],
            boundValuesNum: '',
            boundValuesDate: '',
            separateValid: false,
            spliceMethod: '0',
        };
    }

    /**
     * 修改分支事件
     */
    handleUpdateTree(): void {
        if (!this.currentNode.configId) {
            this.yh_message_warn('请选择节点进行操作!');
            return;
        }
        if (this.currentNode.boundGroupValid) {
            this.yh_message_warn('父节点不支持修改!');
            return;
        }

        // 校验
        if (!this.verifyBoundFormParams()) {
            return;
        }

        let entryBranchConfigs = this.entryBranchConfigs;
        for (let i = 0; i < entryBranchConfigs.length; i++) {
            const element = entryBranchConfigs[i];
            if (element.configId === this.currentNode.configId) {
                element.sqlSpliceType = this.boundForm.sqlSpliceType;
                element.compareType = this.boundForm.compareType;
                element.boundCode = this.boundForm.boundCode;
                element.label =
                    DictionConstUtil.SqlSplicingType[this.boundForm.sqlSpliceType] +
                    ' ' +
                    (this.boundEnum[this.boundForm.boundCode]?.boundName || '') +
                    ' ' +
                    (this.compareDirectionStorage[this.boundForm.compareType] || '') +
                    ' ' +
                    (this.boundForm.boundValueNames || '') +
                    (this.boundForm.separateValid ? '单独控制' : '');

                element.boundValueNames = this.boundForm.boundValueNames || [];
                element.boundValues = this.boundForm.boundValues || [];
                break;
            }
        }

        this.packageEntryBranchConfigs(entryBranchConfigs);
        // 取消选中高亮
        this.currentNode = {};
        // 清空选择框
        this.webShowType = '';
        this.separateValid = false;
        this.boundForm = {
            templateCode: undefined,
            sqlSpliceType: '0',
            compareType: '',
            boundValues: [],
            boundValueNames: [],
            boundValuesNum: '',
            boundValuesDate: '',
            separateValid: false,
            spliceMethod: '0',
        };
    }

    /**
     * 删除分支事件
     */
    handleDeleteTree(): void {
        if (!this.currentNode.configId) {
            this.yh_message_warn('请选择节点进行操作!');
            return;
        }

        // 转为树形结构删除
        let treeData = XEUtils.clone(this.entryBranchConfigsTree, true);
        treeData = recursivefilter(treeData, 'configId', this.currentNode.configId);
        let entryBranchConfigs = treeToArray(treeData);
        // 最外层的范围合并进来 一起组装
        // 1 原有的外层范围
        let data = this.entryBranchConfigs.filter(item => item.groupType !== '0');
        // 2 判断是否还能继续使用
        data = data.filter(item => {
            if (entryBranchConfigs.find(b => b.boundType === item.groupType)) {
                return true;
            }
            return false;
        });
        // 3 合并
        entryBranchConfigs = [...entryBranchConfigs, ...data];
        this.packageEntryBranchConfigs(entryBranchConfigs);

        // 取消选中高亮
        this.currentNode = {};
        // 清空选择框
        this.webShowType = '';
        this.separateValid = false;
        this.boundForm = {
            templateCode: undefined,
            sqlSpliceType: '0',
            compareType: '',
            boundValues: [],
            boundValueNames: [],
            boundValuesNum: '',
            boundValuesDate: '',
            separateValid: false,
            spliceMethod: '0',
        };
    }

    /**
     * 校验范围参数
     */
    verifyBoundFormParams(): boolean {
        const { webgroupType, compareType, boundValues, boundCode, separateValid } = this.boundForm;
        if (!this.boundType) {
            this.yh_message_warn('请选择范围属性再进行配置');
            return false;
        }
        // 添加父节点 跳过检查
        if (boundCode === '-1') {
            return true;
        }
        // 单独控制 跳过检查
        if (separateValid) {
            return true;
        }
        if (boundCode && (!boundValues || boundValues.length === 0)) {
            if (this.separateValid) {
                return true;
            }
            this.yh_message_warn('未配置证券范围值');
            return false;
        }
        if (boundCode && !compareType) {
            this.yh_message_warn('未配置比较方向');
            return false;
        }

        return true;
    }

    /**
     * webShowType = 2 大数据框按钮事件
     */
    selectKeyValueClick(): void {
        this.editLargeDataDialog = this.editLargeDataDialog.getAddDialog('');
        this.transValuesShow = this.boundForm.boundValueNames.toString();
    }

    /**
     * webShowType = 2 穿梭框数据修改事件
     */
    handleEditTrans(): void {
        const rightData = (this.$refs.trans as any).getRightAllData();
        this.boundForm.boundValues = XEUtils.map(rightData, item => item.dictKey);
        this.boundForm.boundValueNames = XEUtils.map(rightData, item => item.dictKeyName);
        this.transValuesShow = this.boundForm.boundValueNames.toString();
        this.editLargeDataDialog.visible = false;
    }

    /**
     * 树点击事件
     * @param node 点击的树节点数据
     */
    handleTreeClick(node: any): void {
        this.recordLastBoundCode = node.boundCode;
        if (node.boundTitle) {
            this.boundType = node.boundType;
        }
        if (node.configId !== this.currentNode.configId && !node.boundTitle) {
            this.currentNode = JSON.parse(JSON.stringify(node));
            this.$nextTick(() => {
                (this.$refs['tree'] as any).setCurrentKey(node.configId);
            });

            if (node.boundType && node.boundType !== this.boundType) {
                this.boundType = node.boundType;
            }
        } else {
            // 取消选中高亮
            this.currentNode = {};
            this.$nextTick(() => {
                (this.$refs['tree'] as any).setCurrentKey();
            });
        }

        // 设置可选比较方向
        this.compareTypes = this.boundEnum[this.currentNode.boundCode]?.webDirections ?? [];
        // 获取下拉框展示类型
        this.webShowType = this.boundEnum[this.currentNode.boundCode]?.webShowType ?? '';
        // 设置是否禁用单独控制
        this.showSeparateValid = this.boundEnum[this.currentNode.boundCode]?.separateValid || false;
        // 设置控制维度
        this.spliceMethods = this.boundEnum[this.currentNode.boundCode]?.spliceMethods ?? [];
        if (['0', '4', '7'].includes(this.webShowType) && !this.currentNode.separateValid) {
            // 获取前端展示SQL
            this.getShowWebSQL(this.currentNode.boundCode);
        }

        if (this.webShowType === '1' || this.webShowType === '5') {
            this.currentNode.boundValuesNum = Number(this.currentNode.boundValues[0]);
        }
        if (this.webShowType === '2' && !this.currentNode.separateValid) {
            this.rightTranData = this.currentNode.boundValues.map((dictKey, i) => ({
                dictKey,
                dictKeyName: this.currentNode.boundValueNames[i],
            }));
            this.transValuesShow = this.currentNode.boundValueNames.toString();
        }
        if (this.webShowType === '3') {
            this.currentNode.boundValuesDate = String(this.currentNode.boundValues[0]) || '';
        }
        if (this.webShowType === '4') {
            this.boundValueSelect = String(this.currentNode.boundValues) || '';
        }

        // 选择框赋值
        this.separateValid = this.currentNode?.separateValid || false;

        this.boundForm = {
            templateCode: undefined,
            boundCode: this.currentNode.boundCode,
            sqlSpliceType: '0',
            compareType: this.currentNode.compareType,
            boundValues: this.currentNode.boundValues || [],
            boundValueNames: this.currentNode.boundValueNames || [],
            boundValuesNum: this.currentNode.boundValuesNum,
            boundValuesDate: this.currentNode.boundValuesDate || '',
            separateValid: this.currentNode.separateValid || false,
            spliceMethod: this.currentNode.spliceMethod || '0',
        };
    }

    /**
     * 获取前端展示SQL
     * @param boundCode
     */
    getShowWebSQL(boundCode: any) {
        if (boundCode === '-1') {
            return;
        }
        this.boundValueCheckStorage = [];
        return new Promise(resolve => {
            this.$axios({ method: 'get', url: '/original/showSelect/' + boundCode }).then(
                (res: any) => {
                    if (res) {
                        this.boundValueOriginalStorage = res;
                        if (this.webShowType === '7') {
                            res.forEach(element => {
                                element.id = element.dictKey;
                                element.label = element.dictKey == 'ROOTKEY' ? element.dictKeyName : element.dictKey + ' ' + element.dictKeyName;
                                element.parentId = element.parentKey;
                            });
                            res = arrayToTree(res);
                        }
                        this.boundValueCheckStorage = res;
                        resolve('success'); //
                    }
                },
                () => {
                    this.boundValueCheckStorage = [];
                    resolve('fail');
                }
            );
        });
    }

    /**
     * 范围属性框变动事件
     * @param val 当前选中数据
     */
    handleBoundTypeChange(val: string): void {
        // 取消选中高亮
        this.currentNode = {};
        this.$nextTick(() => {
            (this.$refs['tree'] as any).setCurrentKey();
        });
        this.boundForm = {
            templateCode: undefined,
            sqlSpliceType: '0',
            compareType: '',
            boundValues: [],
            boundValueNames: [],
            boundValuesNum: '',
            boundValuesDate: '',
            separateValid: false,
            spliceMethod: '0',
        };
        this.separateValid = false;
    }

    /**
     * 范围变动事件
     * @param val 当前选中数据
     */
    handleBoundChange(data: any): void {
        this.selectBoolean = true;
        const val = data.boundCode || '';
        // 清空当前可选方向
        this.boundForm.compareType = '';
        // 清空当前前端展示类型框
        this.boundForm.boundValues = [];
        this.boundForm.boundValueNames = [];
        this.boundForm.boundValuesNum = undefined;
        this.boundForm.boundValuesDate = '';
        this.rightTranData = [];
        this.transValuesShow = '';
        // 设置可选比较方向
        this.compareTypes = this.boundEnum[val]?.webDirections ?? [];
        // 获取下拉框展示类型
        this.webShowType = this.boundEnum[val]?.webShowType ?? '';
        // 设置是否禁用单独控制
        this.showSeparateValid = this.boundEnum[val]?.separateValid;
        // 设置控制维度
        this.spliceMethods = this.boundEnum[val]?.spliceMethods || ['0'];

        if (['0', '4', '7'].includes(this.webShowType)) {
            // 获取前端展示SQL
            this.getShowWebSQL(val);
        }
    }

    handleBoundChange2(data: any): void {
        if (!data) {
            const val = '';
            // 清空当前可选方向
            this.boundForm.compareType = '';
            // 清空当前前端展示类型框
            this.boundForm.boundValues = [];
            this.boundForm.boundValueNames = [];
            this.boundForm.boundValuesNum = undefined;
            this.boundForm.boundValuesDate = '';
            this.rightTranData = [];
            this.transValuesShow = '';
            // 设置可选比较方向
            this.compareTypes = this.boundEnum[val]?.webDirections ?? [];
            // 获取下拉框展示类型
            this.webShowType = this.boundEnum[val]?.webShowType ?? '';
            // 设置是否禁用单独控制
            this.showSeparateValid = this.boundEnum[val]?.separateValid;
            // 设置控制维度
            this.spliceMethods = this.boundEnum[val]?.spliceMethods || ['0'];

            if (['0', '4', '7'].includes(this.webShowType)) {
                // 获取前端展示SQL
                this.getShowWebSQL(val);
            }
        }
    }

    /**
     * 单独控制变动事件
     * @param val 当前选中数据
     */
    handleSeparateValid(val: boolean): void {
        this.boundForm.separateValid = val;
        if (val && this.boundForm.compareType == '') {
            this.boundForm.compareType = '4';
        }
    }

    /**
     * 多种类框变动事件 （前端展示类型）
     * @param val 当前选中数据
     * @param webShowType 展示类型
     */
    handleBoundValueChange(val: any): void {
        if (this.webShowType !== '7') {
            this.boundForm.boundValues = [];
        }
        this.boundForm.boundValueNames = [];

        if (this.webShowType === '0') {
            this.boundForm.boundValues = val;
            val.forEach(element => {
                this.boundValueCheckStorage.forEach(item => {
                    if (element === item.dictKey) {
                        this.boundForm.boundValueNames.push(item.dictKeyName);
                    }
                });
            });
        }
        if (this.webShowType === '1') {
            val = Math.round(val);
            if (val) {
                this.boundForm.boundValues.push(val.toString());
                this.boundForm.boundValueNames.push(val.toString());
            }
        }
        if (this.webShowType === '3') {
            this.boundForm.boundValues.push(val);
            this.boundForm.boundValueNames.push(val);
        }
        if (this.webShowType === '4') {
            this.boundForm.boundValues.push(val);
            for (let i = 0; i < this.boundValueCheckStorage.length; i++) {
                const item = this.boundValueCheckStorage[i];
                if (item.dictKey === val) {
                    this.boundForm.boundValueNames.push(item.dictKeyName);
                    break;
                }
            }
        }
        if (this.webShowType === '5') {
            // val = parseFloat(val);
            this.boundForm.boundValues.push(val.toString());
            this.boundForm.boundValueNames.push(val.toString());
        }
        if (this.webShowType === '7') {
            this.boundForm.boundValues = val;
            val.forEach(element => {
                this.boundValueOriginalStorage.forEach(item => {
                    if (element === item.dictKey) {
                        this.boundForm.boundValueNames.push(item.dictKeyName);
                    }
                });
            });
        }
    }

    /**
     * 指标种类改变事件
     * @param val 当前选中数据
     */
    handleCategoryChange(val: string[]): void {
        let a = val.find((item: any) => {
            return item == '-1';
        });
        if (val.length == 0) {
            this.categoryDis = false;
            this.categoryDisAll = false;
        } else if (a == '-1') {
            this.categoryDis = false;
            this.categoryDisAll = true;
        } else {
            this.categoryDis = true;
            this.categoryDisAll = false;
        }
    }

    /**
     * 请求范围预览表格
     */
    getLookBoundList(): void {
        this.lookBoundLoading = true;
        let data = { boundType: this.boundType, param: this.lookBoundSearchVal, paging: this.lookBoundPage };
        this.$axios({ method: 'post', url: '/original/bound/detail/list', data })
            .then((res: any) => {
                this.lookBoundLoading = false;
                if (res.list) {
                    // eslint-disable-next-line no-return-assign
                    res.list.forEach((item: any, i: any) => (item.rowKey = String(i)));
                    this.lookBoundTableData = res.list;
                    this.lookBoundPage.total = res.total;
                }
            })
            .catch(() => {
                this.lookBoundLoading = false;
            });
    }

    /**
     * 范围预览事件
     */
    handleLookBound(): void {
        if (!this.boundType) {
            this.yh_message_warn('请先选择查询的范围属性');
            return;
        }
        this.lookBoundVisible = true;
        this.getLookBoundList();
    }

    /**
     * 关闭范围预览dialog事件
     */
    handleLookBoundClose(): void {
        this.lookBoundVisible = false;
        this.lookBoundSearchVal = '';
        this.lookBoundTableData = [];
        this.lookBoundPage = { currentPage: 1, pageSize: 20, total: 0, totalPage: 0 };
    }

    /**
     * 给每条范围赋上范围属性字段
     */
    packageBoundType(treeData: any[], boundType?: number | string): any[] {
        for (let i = 0; i < treeData.length; i++) {
            const item = treeData[i];
            if (item.groupType !== '0') {
                item.boundType = item.groupType;
            } else {
                item.boundType = boundType;
            }
            if (item.children) {
                this.packageBoundType(item.children, item.boundType);
            }
        }

        return treeToArray(treeData);
    }

    /**
     * 范围指标动态参数设置
     */
    async handeBoundExtend(item: any) {
        this.FiveData = item;
        if (item.resolveKey || item.boundExtend) {
            await this.handleShowWebShow5(item.boundCode);
            await this.handleShowCompare(item.boundCode);
        }
        this.timeDelayUnit = setTimeout(() => {
            this.showBoundExtendModel = true;
        }, 500);
        this.currentBoundExtend = item;
    }

    /**
     * 根据证券范围配置编号获取范围模板5比较反向
     */
    handleShowCompare(boundCode: string) {
        this.$axios.get('/original/showCompare/' + boundCode).then(
            (res: any) => {
                if (res) {
                    // res.values.forEach((item) => item.key = item.dictKey)
                    this.boundConfigExtends = res;
                }
            },
            () => {
                this.boundConfigExtends = [];
            }
        );
    }

    /**
     * 根据证券范围配置编号获取范围模板5 展示SQL
     */
    handleShowWebShow5(boundCode: string) {
        this.$axios.get('/original/showSelect5/' + boundCode).then(
            (res: any) => {
                if (res) {
                    // res.values.forEach((item) => item.key = item.dictKey)
                    this.selectWebSqlValues5 = res;
                }
            },
            () => {
                this.selectWebSqlValues5 = [];
            }
        );
    }

    /**
     * 范围5 额外配置回调
     * @param {*} action 行为
     * @param {*} configId  范围配置分支id
     * @param {*} value 范围额外配置 boundExtend
     */
    handleBoundExtendModel({ action, configId, value }): void {
        if (action === 'confirm') {
            let entryBranchConfigs = XEUtils.clone(this.entryBranchConfigs, true);
            for (let i = 0; i < entryBranchConfigs.length; i++) {
                const element = entryBranchConfigs[i];
                if (element.boundCode === this.currentBoundExtend.boundCode && element.configId === configId) {
                    element.boundExtend = value;
                    break;
                }
            }
            this.showBoundExtendModel = false;
            this.currentBoundExtend = {};
            this.packageEntryBranchConfigs(entryBranchConfigs);
        } else if (action === 'cancel') {
            this.showBoundExtendModel = false;
        }
    }

    /**
     * 判断是否展示动态参数齿轮 (第五类,第六类)
     */
    showResolveKey(data): any {
        if (data.boundExtend) {
            return { display: '', color: 'green' };
        }
        if (data.resolveKey) {
            if (data.resolveKey.indexOf('|') !== '-1' && data.resolveKey.split('|')[0] == '6') {
                return { display: '', color: data.boundExtend ? 'green' : 'blue' };
            } else if (['5', '6'].includes(data.resolveKey)) {
                return { display: '', color: data.boundExtend ? 'green' : 'blue' };
            }
        }
        return { display: 'none', color: 'blue' };
    }

    /**
     * 单数组 匹配 对象数组
     * @param {array} data 总对象数组
     * @param {array} keys key数组
     */
    match(data: any[], keys: any[]): any[] {
        return keys.reduce((acc, val) => {
            const index = data.findIndex(el => el.boundCode === val);
            return acc.concat(data[index]);
        }, []);
    }

    limitText(count) {
        return `+${count}`;
    }

    /**
     * 组装回数据 将数据传回父组件
     */
    packageEntryBranchConfigs(entryBranchConfigs: any[]): void {
        // let entryBranchConfigs1 = [];
        let entryBranch = {};

        entryBranchConfigs = entryBranchConfigs.sort((a: any, b: any) => a.parentId - b.parentId);

        // // 获取有配置过范围的范围属性
        // let boundTypes = entryBranchConfigs.map(item => item.boundType);
        // boundTypes = [...new Set(boundTypes)];
        // boundTypes = boundTypes.filter(res => res != 'undefined');

        // // 为每个范围属性创建最外层
        // let list = [];
        // for (let b = 0; b < boundTypes.length; b++) {
        //     let data = entryBranchConfigs.find(item => item.boundType === boundTypes[b]);

        //     let obj = {
        //         boundGroupValid: true,
        //         branchNo: this.entryBranch.branchNo,
        //         compareType: '4',
        //         configId: data.configId - 1,
        //         groupType: boundTypes[b],
        //         parentId: 0,
        //         separateValid: false,
        //         sqlSpliceType: '0',
        //     };
        //     list.push(obj);
        // }

        // entryBranchConfigs1 = [...list, ...entryBranchConfigs];
        entryBranch = {
            branchNo: this.entryBranch.branchNo,
            factorCode: this.entryBranch.factorCode,
            entryBranchConfigs,
        };
        this.$emit('set-bound-data', entryBranch);
    }

    /**
     * 对象数组 根据对象内的某个属性去重
     */
    uniqueById(arr) {
        const map = {};
        const result = [];
        for (let i = 0; i < arr.length; i++) {
            const item = arr[i];
            if (!map[item.id]) {
                map[item.id] = true;
                // item.id = item.key;
                // item.label = item.title;
                delete item.children;
                result.push(item);
            }
        }
        return result;
    }

    /**
     * 在树结构中查找某个节点， 并返回与之关联的节点
     */
    findNode(tree, targetId, result = []) {
        for (let i = 0; i < tree.length; i++) {
            const { id, children } = tree[i];
            if (id === targetId) {
                return result.concat(tree[i]);
            } else if (children) {
                const res = this.findNode(children, targetId, result.concat(tree[i]));
                if (res) {
                    return res;
                }
            }
        }
        return null;
    }

    /**
     * 范围属性标题样式
     */
    boundTitleStyle(data: any): any {
        return { 'bound-title': data.boundTitle, 'bound-title-active': this.boundType === data.boundType };
    }
}
</script>
<style lang="scss" scoped>
@import '@/assets/style/item-setting.scss';
/deep/ .el-select__tags-text {
    display: inline-block;
    max-width: 85px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/deep/ .el-tag__close.el-icon-close {
    top: -5px;
}

/deep/ .el-button--mini,
.el-button--mini.is-round {
    padding: 6px 10px;
}

/deep/ .el-select__tags {
    flex-wrap: nowrap;
    overflow: hidden;
    position: absolute;
    left: 2%;
}

.bound-title {
    font-size: 14px;
    font-weight: 600;
}

.bound-title.bound-title-active {
    border: 2px solid rgb(186, 231, 255);
    border-radius: 5px;
}
/deep/ .vue-treeselect {
    height: 26px !important;
    .vue-treeselect__control {
        height: 28px !important;
    }
    .vue-treeselect__multi-value-item-container,
    .vue-treeselect__limit-tip {
        padding-top: 0 !important;
        padding-right: 0 !important;
    }

    .vue-treeselect__input-container {
        padding-top: 0 !important;
        .vue-treeselect__input {
            height: 24px;
            line-height: 24px;
        }
    }

    .vue-treeselect__placeholder,
    .vue-treeselect__single-value {
        height: 28px;
        line-height: 28px;
    }
}
/deep/ .vue-treeselect__option.vue-treeselect__option--highlight {
    min-width: 300px;
}
.type7select /deep/ .vue-treeselect__control {
    padding: 0 !important;
}
/deep/ .vue-treeselect__multi-value-item {
    background-color: #f4f4f5 !important;
    border-color: #e9e9eb !important;
    color: #909399 !important;
    height: 22px !important;
}

.type7select /deep/ .vue-treeselect__limit-tip-text {
    height: 22px !important;
}

.type7select /deep/ .vue-treeselect__multi-value-item-container {
    max-width: 55%;
}

/deep/ .vue-treeselect__multi-value-label {
    height: 22px !important;
    line-height: 22px;
}

// .clear-icon {
//     position: absolute;
//     top: 13px;
//     right: 42px;
//     width: 15px;
//     height: 15px;
//     z-index: 999;
//     cursor: pointer;
// }

/**
 * 隐藏没有匹配到的比较方向 (组节点默认比较方向4)
 */
/deep/ .hidden-value input {
    text-indent: -99px;
}
</style>
<style lang="scss">
.vue-treeselect--open-below .vue-treeselect__menu {
    top: 1px !important;
    height: 28vh !important;
}
.vue-treeselect--open-above .vue-treeselect__menu {
    top: 27px !important;
    height: 28vh !important;
}
/deep/ .vue-treeselect__menu-container .vue-treeselect__menu {
    border: 1px solid red !important;
    position: relative;
    z-index: 99999999 !important;
}
.bound-dialog .el-dialog {
    position: absolute;
    left: 20px;
}
</style>
